#include "buffer.h"

namespace hhfox {

Buffer::Buffer(char* b, int nn) {
    p = bytes = b;
    nb_bytes = nn;
}

Buffer::~Buffer() {}

Buffer* Buffer::copy() {
    Buffer* cp = new Buffer(bytes, nb_bytes);
    cp->p = p;
    return cp;
}

char* Buffer::data() { return bytes; }

char* Buffer::head() { return p; }

void Buffer::seek(size_t pos) {
    assert(pos < nb_bytes);
    p = bytes + pos;
}

int Buffer::size() { return nb_bytes; }

void Buffer::set_size(int v) { nb_bytes = v; }

int Buffer::pos() { return (int)(p - bytes); }

int Buffer::left() { return nb_bytes - pos(); }

bool Buffer::empty() { return !bytes || (p >= bytes + nb_bytes); }

bool Buffer::require(int required_size) {
    if (required_size < 0) return false;
    return required_size <= nb_bytes - pos();
}

void Buffer::skip(int size) {
    assert(p);
    assert(p + size >= bytes);
    assert(p + size <= bytes + nb_bytes);
    p += size;
}

int8_t Buffer::read_1bytes() {
    assert(require(1));
    return (int8_t)*p++;
}

int16_t Buffer::read_2bytes() {
    assert(require(2));
    int16_t value;
    char* pp = (char*)&value;
    pp[1] = *p++;
    pp[0] = *p++;
    return value;
}

int16_t Buffer::read_le2bytes() {
    assert(require(2));
    int16_t value;
    char* pp = (char*)&value;
    pp[0] = *p++;
    pp[1] = *p++;
    return value;
}

int32_t Buffer::read_3bytes() {
    assert(require(3));
    int32_t value = 0x00;
    char* pp = (char*)&value;
    pp[2] = *p++;
    pp[1] = *p++;
    pp[0] = *p++;
    return value;
}

int32_t Buffer::read_le3bytes() {
    assert(require(3));
    int32_t value = 0x00;
    char* pp = (char*)&value;
    pp[0] = *p++;
    pp[1] = *p++;
    pp[2] = *p++;
    return value;
}

std::string Buffer::read_string(int len) {
    assert(require(len));
    std::string value;
    value.append(p, len);
    p += len;
    return value;
}

void Buffer::read_byte(char* data, int size) {
    assert(require(size));
    memcpy(data, p, size);
    p += size;
}

void Buffer::write_1bytes(int8_t value) {
    assert(require(1));
    *p++ += value;
}

void Buffer::write_2bytes(int16_t value) {
    assert(require(2));
    char* pp = (char*)&value;
    *p++ = pp[1];
    *p++ = pp[0];
}

void Buffer::write_le2bytes(int16_t value) {
    assert(require(2));
    char* pp = (char*)&value;
    *p++ = pp[0];
    *p++ = pp[1];
}

void Buffer::write_3bytes(int32_t value) {
    assert(require(3));
    char* pp = (char*)&value;
    *p++ = pp[2];
    *p++ = pp[1];
    *p++ = pp[0];
}

void Buffer::write_le3bytes(int32_t value) {
    assert(require(3));
    char* pp = (char*)&value;
    *p++ = pp[0];
    *p++ = pp[1];
    *p++ = pp[2];
}

void Buffer::write_string(std::string value) {
    assert(require((int)value.size()));
    memcpy(p, value.data(), value.length());
    p += value.length();
}

void Buffer::write_bytes(char* data, int size) {
    assert(require(size));
    memcpy(p, data, size);
    p += size;
}

VBuffer::~VBuffer() { current_pos_ = 0; }

void VBuffer::seek(size_t pos) {
    if (pos <= buffer_.size()) {
        current_pos_ = pos;
    } else {
        // 处理超出范围的情况，这里简单地将当前位置设置为缓冲区末尾
        current_pos_ = buffer_.size();
    }
}

void VBuffer::write_1bytes(int8_t value) {
    buffer_.push_back(static_cast<unsigned char>(value));
    current_pos_++;
}

void VBuffer::write_2bytes(int16_t value) {
    char* pp = (char*)&value;
    buffer_.push_back(pp[1]);
    buffer_.push_back(pp[0]);
    current_pos_ += 2;
}

void VBuffer::write_le2bytes(int16_t value) {
    char* pp = (char*)&value;
    buffer_.push_back(pp[0]);
    buffer_.push_back(pp[1]);
    current_pos_ += 2;
}

void VBuffer::write_3bytes(int32_t value) {
    char* pp = (char*)&value;
    buffer_.push_back(pp[2]);
    buffer_.push_back(pp[1]);
    buffer_.push_back(pp[0]);
    current_pos_ += 3;
}

void VBuffer::write_le3bytes(int32_t value) {
    char* pp = (char*)&value;
    buffer_.push_back(pp[0]);
    buffer_.push_back(pp[1]);
    buffer_.push_back(pp[2]);
    current_pos_ += 3;
}

void VBuffer::write_bytes(unsigned char* data, int size) {
    if (current_pos_ < buffer_.size()) {
        // 如果当前位置小于缓冲区大小，则覆盖现有数据
        std::memcpy(&buffer_[current_pos_], data, size);
    } else {
        // 如果当前位置等于或超出缓冲区大小，则追加数据到缓冲区末尾
        buffer_.insert(buffer_.end(), data, data + size);
    }
    // 更新当前位置
    current_pos_ += size;
}

} // namespace hhfox